﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Windows.Forms;
using Sunny.UI;

namespace SmartMotion.Core
{
    public partial class FrmDllFunction : UIForm
    {
        #region 字段

        private readonly DllFunction _dllFunction;
        private readonly List<string> _paraTypes;
        private readonly List<string> _paraNames;
        private List<Type> _typeList;
        private List<MethodInfo> _funList;
        #endregion

        public FrmDllFunction(DllFunction dllFunction)
        {
            _dllFunction = dllFunction;
            _paraTypes = new List<string>();
            _paraNames = new List<string>();
            InitializeComponent();
        }

        private void FrmDllFunction_Load(object sender, EventArgs e)
        {
            RefreshDll(false);
        }
        //刷新DLL，加载上一次的配置
        private void RefreshDll(bool loadAll = true)
        {
            var files = Directory.GetFiles(Environment.CurrentDirectory, "*.dll");
            lstDll.Items.Clear();
            foreach (var file in files)
            {
                try
                {
                    var types = ReflectAble.GetTypes(file, loadAll);
                    if (types.Count > 0)
                    {
                        lstDll.Items.Add(Path.GetFileName(file));
                    }
                }
                catch (Exception exception)
                {
                    Console.WriteLine(exception);
                }
            }

            #region 加载上一次的配置

            int index = lstDll.Items.IndexOf(_dllFunction.Dll);
            lstDll.SelectedIndex = index;

            foreach (var type in _typeList)
            {
                if (type.FullName==_dllFunction.TypeName)
                {
                    lstType.SelectedItem = type;
                    break;
                }
            }

            foreach (var methodInfo in _funList)
            {
                if (methodInfo.Name==_dllFunction.MethodName)
                {
                    if (methodInfo.GetParameters().Length == _dllFunction.ParaTypes.Count)
                    {
                        lstMethod.SelectedItem = methodInfo;
                        break;
                    }
                    
                }
            }
            txtName.Text = _dllFunction.ItemName;

            #endregion
        }
        //选择dll后把dll的可用类型绑定到lstType
        private void lstDll_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (lstDll.SelectedItem == null) return;
            string fileName = Environment.CurrentDirectory + "\\" + lstDll.SelectedItem; 
            _typeList = ReflectAble.GetTypes(fileName);
            BindingSource bs = new BindingSource();
            bs.DataSource = _typeList;
            lstType.DataSource = bs;
            lstType.DisplayMember = "Name";
        }

        //选择类型后把可用函数绑定到lstMethod
        private void lstType_SelectedIndexChanged(object sender, EventArgs e)
        {
            _funList = ReflectAble.GetMethods(lstType.SelectedItem as Type);
            BindingSource bs = new BindingSource();
            bs.DataSource = _funList;
            lstMethod.DataSource = bs;
            lstMethod.DisplayMember = "signature";
        }
        //选择方法后把参数名称，参数类型拿出来放到_paraNames,_paraTypes里，给保存按钮使用
        private void lstMethod_SelectedIndexChanged(object sender, EventArgs e)
        {
            var medInfo = lstMethod.SelectedItem as MethodInfo;
            if (medInfo==null)return;

            var methodParams = medInfo.GetParameters();
            _paraNames.Clear();
            _paraTypes.Clear();

            foreach (var parameterInfo in methodParams)
            {
                _paraNames.Add(parameterInfo.Name);
                _paraTypes.Add(parameterInfo.ParameterType.FullName);
            }
        }

        //保存一次性函数
        private void btnSave_Click(object sender, EventArgs e)
        {
            if (txtName.Text.Length==0)
            {
                ShowErrorDialog("请输入一个名称");
                return;
            }

            _dllFunction.ItemName = txtName.Text;
            _dllFunction.Dll = lstDll.SelectedItem.ToString();
            _dllFunction.TypeName = (lstType.SelectedItem as Type)?.FullName;

            _dllFunction.MethodName = (lstMethod.SelectedItem as MethodInfo)?.Name;
            _dllFunction.IsStatic = ((MethodInfo) lstMethod.SelectedItem).IsStatic;
            _dllFunction.Parms.Clear();
            _dllFunction.ParaTypes.Clear();
            _dllFunction.ParaNames.Clear();
            _dllFunction.ReturnType = ((MethodInfo) lstMethod.SelectedItem).ReturnType.FullName;
            _paraTypes.ForEach(item=>_dllFunction.ParaTypes.Add(item));
            _paraNames.ForEach(item=>_dllFunction.ParaNames.Add(item));
            for (int i = 0; i < _paraTypes.Count; i++)
            {
                string item = _paraTypes[i];
                _dllFunction.Parms.Add(new MethodParms(){Name = _paraNames[i],Type = item,InputOrSelect = true});
            }

            DialogResult = DialogResult.OK;
            Close();

        }
        //刷新DLL
        private void btnRefresh_Click(object sender, EventArgs e)
        {
            RefreshDll(ckbLoadAll.Checked);
        }
        //取消
        private void btnCancel_Click(object sender, EventArgs e)
        {
            Close();
        }
    }
}
    